#include "../include/mutex.h"
#include "../include/data_hand.h"
#include "../include/data_global.h"
#include "../include/sem.h"

#include <semaphore.h>
#include <termios.h>

uint32_t ill_msg;					//存储光照信息
uint8_t  hum_msg[2];                //存储湿度
uint8_t  temp_msg[2];  				//温度信息存储
extern unsigned char dev_camera_mask;      //存放控制摄像头指令
extern unsigned char dev_buzzer_mask;		//存放控制蜂鸣器指令
extern unsigned char dev_uart_mask;		//存放控制M0指令

extern int dev_uart_fd;             //M0串口设备文件描述符
extern int dev_infrared_fd;         //按键设备文件描述符
extern int dev_camera_fd;					//摄像头设备文件描述符
extern int msgid;							//消息队列id
extern int dev_led_fd;				//A9板LED设备号 
extern int dev_led_mask;

struct env_info serial_data = {};    //头文件：sem.h
struct msg msgbuf; //消息队列结构体

struct setEnv     
{
	int temMAX;
	int temMIN;
	int humMAX;
	int humMIN;
	int illMAX;
	int illMIN;
};

struct setEnv new_env;

struct setEnv current_env = {
	.temMAX = 40,
	.temMIN = 10,
	.humMAX = 100,
	.humMIN = 90,
	.illMAX = 600,
	.illMIN = 50
	
};

/*功能：串口初始化
  参数：串口设备文件描述符
 */
void serial_init(int fd)
{
    struct termios options;
    tcgetattr(fd, &options);
    options.c_cflag |= ( CLOCAL | CREAD );
    options.c_cflag &= ~CSIZE;
    options.c_cflag &= ~CRTSCTS;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CSTOPB;
    options.c_iflag |= IGNPAR;
    options.c_iflag &= ~(ICRNL | IXON);
    options.c_oflag = 0;
    options.c_lflag = 0;

    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    tcsetattr(fd,TCSANOW,&options);
}


/*** 共享内存线程 ***/
void *DataUpload_hand(void *arg)
{

    sem_t sem;
    fisrt_init_sem(); //初始化信号灯
    init_mem(); //初始化共享内存
    if(sem_init(&sem, 0, 0) < 0) //初始化信号量
    {
        perror("fail to sem_init");
        exit(-1);
    }
   // pthread_cond_wait(&buffer.notempty, (pthread_mutex_t *)NULL);
    puts("upload_thread : sleep ...");
    sleep(2);
    while(1)
    {   

        //puts("共享内存while上");	
        sem_p(semid,0);
        /*******************锁**********/
        pthread_mutex_lock(&recvdata_lock);
        *shm_buf = serial_data;
        pthread_mutex_unlock(&recvdata_lock);
        /*******************开锁**********/
        sem_v(semid,0);
		//puts("共享内存while下");	
        sleep(1);
    }

//    pthread_cond_destroy(&buffer.notempty);


}

/*** 数据保存线程 ***/
void *DataSave_hand(void *arg) //数据保存线程
{
    int i = 0;
    linkhead_t *l = create_linklist();
    sleep(2);


    while(1)
    {
        i ++;
        /*******************锁**********/
        pthread_mutex_lock(&recvdata_lock);
        insert_linklist(0, serial_data, l);
        pthread_mutex_unlock(&recvdata_lock);
        /*******************开锁**********/
        if(i == 10)
        {
            i = 0;
            printf("l -> len : %d\n", l->len);
            show_linklist(l);

            
            clear_link(l);
        }
        sleep(1);

    }


}

/*** M0串口读线程 ***/
void *recv_hand(void *fd)
{
    if( (dev_uart_fd = open("/dev/ttyUSB0", O_RDWR, 0666) ) < 0)
    {
        perror("fail to open ttyUSB0");
        exit(-1);
    }
    serial_init(dev_uart_fd); //串口初始化

	while(1)
	{
		printf("on read\n");

        /*******************锁**********/
		pthread_mutex_lock(&mutex_uart);
        pthread_mutex_lock(&recvdata_lock);
		
    	read(dev_uart_fd, &serial_data, sizeof(struct env_info));
	
		pthread_mutex_lock (&mutex_m0_over_ctl);
		ill_msg = serial_data.ill;
		pthread_mutex_unlock (&mutex_m0_over_ctl);
		pthread_cond_signal (&cond_m0_over_ctl);
		
        pthread_mutex_unlock(&recvdata_lock);
		pthread_mutex_unlock(&mutex_uart);
        /*******************开锁**********/
		printf("behind read\n");
//     	printf("x:%d y:%d z:%d\n", serial_data.x, serial_data.y, serial_data.z);
	//  pthread_cond_signal(&buffer.notempty);
     	sleep(1);	
	}
}

/*** 红外检测（按键模拟）线程 实现触发 激活蜂鸣器报警 短信***/
void *pthread_infrared(void *arg)
{
	int len;
	char buf;
	char check = 'x';  //????????0或1
	if ((dev_infrared_fd = open (DEV_INFRARED, O_RDWR)) < 0)
	{
		perror ("open infrared");
		//exit (-1);
		exit(-1);
	}
	printf ("pthread_infrared is ok\n");
	while (1)
	{
		buf = 0;
		len = read (dev_infrared_fd, &buf, sizeof (char));
		//printf ("*******按键读取数据为 %d\n", buf);
		if (check != buf)
		{
			check = buf;
			pthread_cond_signal (&cond_buzzer);
			pthread_cond_signal (&cond_sms);
		}
	}
}

/**   客户端请求控制M0的线程  **/
void *pthread_uart_cmd(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex_uart_cmd);
		pthread_cond_wait(&cond_uart_cmd,&mutex_uart_cmd);
		//puts("in 客户端指令写入M0线程");
		pthread_mutex_lock(&mutex_uart);						
		write (dev_uart_fd,&dev_uart_mask,1);
		pthread_mutex_unlock(&mutex_uart);
							
	
		pthread_mutex_unlock(&mutex_uart_cmd);
		//puts("客户端指令写入M0线程");
	}
	return 	NULL;
}

/***  摄像头控制线程  ***/
void *pthread_camera (void *arg)
{
	unsigned char picture = 0;
//	char *buf = NULL;

	if ((dev_camera_fd = open (DEV_CAMERA, O_RDWR | O_NOCTTY | O_NDELAY)) < 0)
	{
		printf ("Cann't open file /tmp/webcom\n");
		exit (-1);
	}
	printf ("pthread_camera is ok\n");
#if 0
	if ((buf = (char *)malloc(10)) == NULL)
	{
		printf("In pthread_camera malloc failed!\n");
		return NULL;
	}
#endif
	while (1)	
	{
		pthread_mutex_lock (&mutex_camera);
		pthread_cond_wait (&cond_camera, &mutex_camera);
		picture = dev_camera_mask;
		printf("dev_camera_mask = %d\n", dev_camera_mask);
		pthread_mutex_unlock (&mutex_camera);

		switch (picture){
			case 1:
	//		buf = "one";
			write (dev_camera_fd, "one", 3);		
			break;		
			case 3:
	//		buf = "three";
			write (dev_camera_fd, "three", 5);		
			break;
			case 5:
	//		buf = "five";
			write (dev_camera_fd, "five", 4);
			break;
			case 7:
	//		buf = "seven";
			write (dev_camera_fd, "seven", 5);
			break;
			case 9:
	//		buf = "nine";
			write (dev_camera_fd, "nine", 9);
			break;
			default:
			break;
		}
	}
}

/*** M0数据超过上限自动报警线程 只加了光照，其他在if判断里或上***/
void *pthread_M0over_ctl(void *args)
{
	int flag = 0;
	char beep_on = 0x91,beep_off = 0x90,led_on = 0xa1,led_off = 0xa0,fan_on = 0x82,fan_off = 0x80;
	struct setEnv env_limit_msg;
	while(1)
	{
		pthread_mutex_lock(&mutex_limit);
		env_limit_msg = current_env;
		pthread_mutex_unlock(&mutex_limit);
		
		printf("****in baojing while\n");
		pthread_mutex_lock (&mutex_m0_over_ctl);
		pthread_cond_wait (&cond_m0_over_ctl, &mutex_m0_over_ctl);
		printf("ill : %d\n",ill_msg);
		if(ill_msg > env_limit_msg.illMAX)
		{
			flag = 1;
			printf("****in baojing if\n");
			pthread_mutex_unlock (&mutex_m0_over_ctl);
			
			printf("****on devuartmask\n");
			pthread_mutex_lock(&mutex_uart);						
			write (dev_uart_fd,&beep_on,1);
			pthread_mutex_unlock(&mutex_uart);
			
		}else if(ill_msg < env_limit_msg.illMIN)
		{
			flag = 2;
			pthread_mutex_unlock (&mutex_m0_over_ctl);
			
			pthread_mutex_lock(&mutex_uart);						
			write (dev_uart_fd,&led_on,1);
			pthread_mutex_unlock(&mutex_uart);
		}else{
			pthread_mutex_unlock (&mutex_m0_over_ctl);
			switch(flag)
			{
				case 1:
						pthread_mutex_lock(&mutex_uart);						
						write (dev_uart_fd,&beep_off,1);
						pthread_mutex_unlock(&mutex_uart);
						flag  = 0;
						break;
				case 2:
						pthread_mutex_lock(&mutex_uart);						
						write (dev_uart_fd,&led_off,1);
						pthread_mutex_unlock(&mutex_uart);
						flag  = 0;
						break;
				default :
						break;
			}
		}
		sleep(1);
		
	}
	
}

/***下行主线程***/
void *pthread_client_request (void *arg)
{
	key_t key;
	ssize_t msgsize;

	if ((key = ftok ("/app", 'g')) < 0)
	{
		perror ("ftok msgqueue");
		exit (-1);
	}
    puts("-----------1---------------");
	if ((msgid = msgget (key, IPC_CREAT | IPC_EXCL | 0666)) < 0)
	{
		if(errno == EEXIST)
		{
			msgid = msgget (key,0666);
    puts("-----------2---------------");
		} 
		else
		{
			perror ("msgget msgid");
			exit (-1);
		}
	}

	printf ("pthread_client_request is ok\n");
	while (1)
    {
        bzero (&msgbuf, sizeof (msgbuf));
        printf ("wait for the msg\n");
        msgsize = msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0);
        printf ("Get %ldL msg\n", msgbuf.msgtype);
        printf ("text[0] = %#x\n", msgbuf.text[0]);
        switch (msgbuf.msgtype)
        {
            case 1L:
                {
                    pthread_mutex_lock (&mutex_led);
                    dev_led_mask = msgbuf.text[0];
                    pthread_cond_signal (&cond_led);
                    pthread_mutex_unlock (&mutex_led);

                    break;
                }
            case 2L:
                {
                    pthread_mutex_lock (&mutex_buzzer);
                    dev_buzzer_mask = msgbuf.text[0];
                    printf("msgbuf.text[0] = %d \n",msgbuf.text[0]);
                    pthread_cond_signal (&cond_buzzer);
                    pthread_mutex_unlock (&mutex_buzzer);
                    break;
                }
            case 3L:
                {
                    pthread_mutex_lock (&mutex_camera);
                    dev_camera_mask = msgbuf.text[0];
                    pthread_cond_signal (&cond_camera);
                    pthread_mutex_unlock (&mutex_camera);
                    break;
                }
            case 4L:
                {
                    // pthread_cond_wait(&cond_uart,&mutex_uart_cmd);    //信号用于读写的同步
                    pthread_mutex_lock (&mutex_uart_cmd);	
                    dev_uart_mask = msgbuf.text[0];
                    printf("msgbuf.text = %d\n",msgbuf.text[0]);
                    pthread_mutex_unlock (&mutex_uart_cmd);

                    pthread_cond_signal (&cond_uart_cmd);

                    puts("client request : 4L");

                    //char p = 0x91;

                    //write(dev_uart_fd, &p , 1);

                    break;
                }
            case 5L:    //数据上限下限
                {

                    memcpy (&new_env, msgbuf.text + 1, 24);
                    pthread_mutex_lock(&mutex_limit);
                    if(new_env.temMAX > 0 && new_env.temMAX > current_env.temMIN)
                    {
                        current_env.temMAX = new_env.temMAX; 
                    }
                    if(new_env.temMIN > 0 && new_env.temMIN < current_env.temMAX)
                    {
                        current_env.temMIN = new_env.temMIN;
                    }
                    if(new_env.humMAX > 0 && new_env.humMAX > current_env.humMIN)
                    {
                        current_env.humMAX = new_env.humMAX;
                    }
                    if(new_env.humMIN > 0 && new_env.humMIN < current_env.humMAX)
                    {	 
                        current_env.humMIN = new_env.humMIN; 
                    }
                    if(new_env.illMAX > 0 && new_env.illMAX > current_env.illMIN)
                    {
                        current_env.illMAX = new_env.illMAX;
                    }
                    if(new_env.illMIN > 0 && new_env.illMIN < current_env.illMAX)
                    {
                        current_env.illMIN = new_env.illMIN;
                    }
                    pthread_mutex_unlock(&mutex_limit);
                    /*
                       memcpy (&new, msgbuf.text + 1, 24);
                       sto_no = msgbuf.text[0] - 48;
                       printf ("sto_no = %d temMAX = %d, temMIN = %d, humMAX = %d, hunMIN = %d, illMAX = %d, illMIN = %d\n",
                       sto_no, new.temMAX, new.temMIN, new.humMAX, new.humMIN, new.illMAX, new.illMIN);
                       pthread_mutex_lock (&mutex_global);
                       if (new.temMAX > 0 && new.temMAX > all_info_RT.storage_no[sto_no].temperatureMIN)
                       {
                       all_info_RT.storage_no[sto_no].temperatureMAX = new.temMAX;
                    //		printf("new.temMAX =%d\n", new.temMAX);
                    }
                    if (new.temMIN > 0 && new.temMIN < all_info_RT.storage_no[sto_no].temperatureMAX)
                    {
                    all_info_RT.storage_no[sto_no].temperatureMIN = new.temMIN;
                    //		printf("new.temMIN = %d\n", new.temMIN);
                    }
                    if (new.humMAX > 0 && new.humMAX > all_info_RT.storage_no[sto_no].humidityMIN)
                    {
                    all_info_RT.storage_no[sto_no].humidityMAX = new.humMAX;
                    //		printf("new.humMAX = %d\n", new.humMAX);
                    }
                    if (new.humMIN > 0 && new.humMIN < all_info_RT.storage_no[sto_no].temperatureMAX)
                    {
                    all_info_RT.storage_no[sto_no].humidityMIN = new.humMIN;
                    //		printf("new.humMIN = %d\n", new.humMIN);
                    }
                    if (new.illMAX > 0 && new.illMAX > all_info_RT.storage_no[sto_no].illuminationMIN)
                    {
                    all_info_RT.storage_no[sto_no].illuminationMAX = new.illMAX;
                    //		printf("new.illMAX = %d\n", new.illMAX);
                    }
                    if (new.illMIN > 0 && new.illMIN < all_info_RT.storage_no[sto_no].illuminationMAX)
                    {
                    all_info_RT.storage_no[sto_no].illuminationMIN = new.illMIN;
                    //		printf("new.illMIN = %d\n", new.illMIN);
                    }
                    pthread_mutex_lock (&mutex_slinklist);
                    sqlite_InsertLinknode (ENV_UPDATE, all_info_RT, sto_no, 0);//0,0分别是仓库号和货物种类号
                    pthread_mutex_unlock (&mutex_slinklist);
                    pthread_cond_signal (&cond_sqlite);
                    pthread_mutex_unlock (&mutex_global);
                    pthread_cond_signal (&cond_refresh);
                    */
                    break;

                }
            default : break;
        }
    }

}

